<template>
  <div class="upload-container">
    <!-- 上传组件 -->
    <el-upload
      class="upload-demo"
      drag
      multiple
      :auto-upload="false"
      :on-change="handleFileChange"
      :show-file-list="false"
    >
      <el-icon class="el-icon--upload"><upload-filled /></el-icon>
      <div class="el-upload__text">
        将文件拖到此处，或
        <em>点击选择</em>
      </div>
    </el-upload>

    <!-- 上传文件列表 -->
    <div class="file-list">
      <div v-for="file in fileList" :key="file.uid" class="file-item">
        <div class="file-info">
          <span class="file-name">{{ file.name }}</span>
          <el-progress :percentage="file.percentage" :status="file.status" :stroke-width="16" />
        </div>
        <div class="file-actions">
          <el-button v-if="file.status === 'success'" type="primary" link @click="handlePreview(file)">预览</el-button>
          <el-button v-if="file.status === 'success'" type="success" link @click="handleDownload(file)">下载</el-button>
          <el-button v-if="file.status === 'exception'" type="danger" link @click="retryUpload(file)">重试</el-button>
        </div>
      </div>
    </div>

    <!-- 预览弹窗 -->
    <el-dialog v-model="previewVisible" title="文件预览">
      <img v-if="previewType === 'image'" :src="previewUrl" class="preview-image" />
      <embed v-else-if="previewType === 'pdf'" :src="previewUrl" type="application/pdf" width="100%" height="600px" />
      <div v-else>暂不支持该格式预览</div>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'
import { ElMessage } from 'element-plus'
import axios from 'axios'

// 分片大小 (1MB)
const CHUNK_SIZE = 1 * 1024 * 1024

const fileList = ref([])
const previewVisible = ref(false)
const previewUrl = ref('')
const previewType = ref('')

// 处理文件选择
const handleFileChange = async uploadFile => {
  const file = uploadFile.raw
  if (!file) return

  // 初始化文件对象
  const fileItem = {
    uid: file.uid,
    name: file.name,
    size: file.size,
    raw: file,
    percentage: 0,
    status: 'ready',
    chunks: Math.ceil(file.size / CHUNK_SIZE),
    uploadedChunks: 0
  }

  fileList.value.push(fileItem)
  await startUpload(fileItem)
}

// 开始分片上传
const startUpload = async fileItem => {
  try {
    fileItem.status = 'uploading'

    // 创建文件读取器
    const reader = new FileReader()
    const file = fileItem.raw

    // 分片上传逻辑
    for (let chunkIndex = 0; chunkIndex < fileItem.chunks; chunkIndex++) {
      const start = chunkIndex * CHUNK_SIZE
      const end = Math.min(file.size, start + CHUNK_SIZE)
      const chunk = file.slice(start, end)

      const formData = new FormData()
      formData.append('file', chunk)
      formData.append('chunkIndex', chunkIndex)
      formData.append('totalChunks', fileItem.chunks)
      formData.append('fileName', file.name)
      formData.append('fileHash', fileItem.uid)

      const { data } = await axios.post('/api/upload', formData, {
        onUploadProgress: progressEvent => {
          const chunkPercent = Math.round((progressEvent.loaded / progressEvent.total) * 100)
          const totalPercent = Math.round(((fileItem.uploadedChunks + chunkPercent / 100) / fileItem.chunks) * 100)
          fileItem.percentage = totalPercent
        }
      })

      if (data.success) {
        fileItem.uploadedChunks++
      }
    }

    // 合并请求
    const { data } = await axios.post('/api/merge', {
      fileName: file.name,
      fileHash: fileItem.uid,
      totalChunks: fileItem.chunks
    })

    if (data.success) {
      fileItem.status = 'success'
      fileItem.url = data.url
    }
  } catch (error) {
    fileItem.status = 'exception'
    ElMessage.error('上传失败: ' + error.message)
  }
}

// 文件预览
const handlePreview = file => {
  if (!file.url) return

  const ext = file.name.split('.').pop().toLowerCase()
  previewType.value = ['jpg', 'jpeg', 'png', 'gif'].includes(ext) ? 'image' : ext === 'pdf' ? 'pdf' : 'other'

  previewUrl.value = file.url
  previewVisible.value = true
}

// 文件下载
const handleDownload = file => {
  if (!file.url) return

  const link = document.createElement('a')
  link.href = file.url
  link.download = file.name
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

// 重试上传
const retryUpload = file => {
  file.status = 'ready'
  file.percentage = 0
  startUpload(file)
}
</script>

<style scoped>
.upload-container {
  max-width: 800px;
  margin: 20px auto;
  padding: 20px;
}

.file-list {
  margin-top: 20px;
}

.file-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px;
  margin-bottom: 10px;
  border: 1px solid #ebeef5;
  border-radius: 4px;
}

.file-info {
  flex: 1;
  margin-right: 20px;
}

.file-name {
  display: block;
  margin-bottom: 8px;
  font-size: 14px;
}

.preview-image {
  max-width: 100%;
  max-height: 80vh;
  display: block;
  margin: 0 auto;
}
</style>
